home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / modprolg / mod-prol.lha / Prolog / modlib / src / $decompile.P < prev    next >
Encoding:
Text File  |  1992-05-21  |  34.3 KB  |  1,032 lines

  1. /************************************************************************
  2. *                                    *
  3. * The SB-Prolog System                            *
  4. * Copyright SUNY at Stony Brook, 1986; University of Arizona,1987    *
  5. *                                    *
  6. ************************************************************************/
  7.  
  8. /*-----------------------------------------------------------------
  9. SB-Prolog is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY.  No author or distributor
  11. accepts responsibility to anyone for the consequences of using it
  12. or for whether it serves any particular purpose or works at all,
  13. unless he says so in writing.  Refer to the SB-Prolog General Public
  14. License for full details.
  15.  
  16. Everyone is granted permission to copy, modify and redistribute
  17. SB-Prolog, but only under the conditions described in the
  18. SB-Prolog General Public License.   A copy of this license is
  19. supposed to have been given to you along with SB-Prolog so you
  20. can know your rights and responsibilities.  It should be in a
  21. file named COPYING.  Among other things, the copyright notice
  22. and this notice must be preserved on all copies. 
  23. ------------------------------------------------------------------ */
  24.  
  25. /****************************************************************************
  26.  *                                                                          *
  27.  * This file has been changed by to include Modules Extensions              *
  28.  * Changes by : Brian Paxton 1991/92                                        *
  29.  * Last update : June 1992                                                  *
  30.  *                                                                          *
  31.  * Organisation : University of Edinburgh.                                  *
  32.  * For : Departments of Computer Science and Artificial Intelligence        * 
  33.  *       Fourth Year Project.                                               *
  34.  *                                                                          *
  35.  ****************************************************************************/
  36.  
  37. /* This file contains predicates that traverse a buffer containing
  38.    asserted code, and reconstruct the clause that was asserted.  This
  39.    code is tied fairly tightly to the code generated by "assert", so
  40.    changes to assert may require corresponding updates to this code.
  41.    This also means that compiled code (i.e. that generated by "compile")
  42.    cannot be decompiled.                    */
  43.  
  44. $decompile_export([$clause/2,$clause/3,$listing/1,$instance/2,
  45.                    $oldlisting/0,$listing/0,$list_module/1]).
  46.  
  47. % $decompile_use : $bio $buff $bmeta $meta $assert $blist $deb $currsym
  48.  
  49. $clause(Hd,Body) :- $clause(Hd,Body,_,1).
  50.  
  51. $clause(Hd,Body,Ref) :- $clause(Hd,Body,Ref,1).
  52.  
  53. $clause(Hd,Body,Ref,Xform) :-
  54.      nonvar(Hd),
  55.      !,
  56.      $decompile(Hd, Body, Ref, Xform).
  57. $clause(Hd,Body,Ref,Xform) :-
  58.      $is_buffer(Ref),    /* better be a DB ref! */
  59.      $dec_getpsc(Ref,16,_,Psc),
  60.      $mkstr(Psc,Hd0,Arity),
  61.      !,
  62.      $decompile_clause(Ref,Arity,Hd0,Body0),
  63.      (Body0 ?= true ->
  64.           (Hd = Hd0, Body = Body0) ;
  65.       (arg(Arity,Hd0,CutArg),
  66.        $dec_xform(Body0,CutArg,Body,Xform),
  67.        RArity is Arity - 1,
  68.        $functor(Hd0,Pred,_), $functor(Hd,Pred,RArity),
  69.        $dec_copyargs(RArity,Hd0,Hd)
  70.       )
  71.      ).
  72. $clause(Hd,B,R,_) :-
  73.      $telling(X), $tell(stderr),
  74.      $writename('*** Error: illegal argument(s) to clause/[2,3]: <'), 
  75.      $write(Hd), $write(', '), $write(B), $write(', '), $write(R), $write('> ***'), $nl,
  76.      $told, $tell(X),
  77.      fail.
  78.  
  79. % The old version of listing is still available here as $oldlisting/0
  80.  
  81. $oldlisting :-
  82.      $predicate_property(X,interpreted),
  83.      $functor(X,P,N),
  84.      $listing(P/N),
  85.      fail.
  86. $oldlisting.
  87.  
  88. $listing(Pred) :- $listing(Pred,1).
  89.  
  90. $listing([],_) :- !.
  91. $listing([H|L],Xform) :-
  92.      !,
  93.      ($listing(H,Xform) -> true ; true),   /* do the rest anyway */
  94.      $listing(L,Xform).
  95. $listing(Pred,Xform) :-
  96.      nonvar(Pred) ->
  97.           (Pred = P/N ->
  98.            ($functor(Hd,P,N),
  99.             ($decompile(Hd,Body,_,Xform),
  100.              $portray_clause((Hd :- Body)),
  101.              fail    /* backtrack to get all clauses */
  102.             ) ;
  103.             true
  104.            ) ;
  105.            ($errmsg('*** Error: argument to listing/1 must be of the form <pred>/<arity>'), $nl
  106.            )
  107.       ) ;
  108.         ($errmsg('*** Error: argument to listing/1 must be instantiated ***'), fail).
  109.  
  110.  
  111. $instance(Ref, Instance) :-
  112.      $is_buffer(Ref) ->
  113.           $instance_1(Ref, Instance) ;
  114.       ($telling(X), $tell(stderr),
  115.        $write('*** Error: argument 1 of instance/2 must be a DB reference ***'), $nl,
  116.        $told, $tell(X),
  117.        fail
  118.       ).
  119.  
  120. $instance_1(Ref, Instance) :-
  121.      $clause(H, B, Ref),
  122.      (H = '_$record_db'(_, Instance) ->
  123.           true ;
  124.       Instance = (H :- B)
  125.      ).
  126.  
  127. $dec_getbuffwd(Buff,Li,Lo,Word) :-
  128.     Lo is Li+2, $buff_code(Buff,Li,6 /* gb */,Word).
  129.  
  130. $dec_getbuffnum(Buff,Li,Lo,Num) :-
  131.     Lo is Li+4, $buff_code(Buff,Li,5 /* gn */,Num).
  132.  
  133. $dec_getbuffloat(Buff,Li,Lo,Num) :-
  134.     Lo is Li+4, $buff_code(Buff,Li,29 /* gf */,Num).
  135.  
  136. $dec_getpsc(Buff,Li,Lo,Psc) :-
  137.     Lo is Li+4, $buff_code(Buff,Li,28 /* gppsc */, Psc).
  138.  
  139. $decompile(Head, Body, Clref, Xform) :-
  140.      $functor(Head,P,N),
  141.      $symtype(Head, Type),
  142.      (Type =\= 1 ->
  143.           ($dec_errmsg(Type,P,N), fail) ;
  144.       ($dec_GetPrref(Head,Prref),
  145.            $buff_code(Prref,8,8 /* gpb */, FirstClref),
  146.        $clause_addr(FirstClref, Clref,P,N),
  147.        NArity is N + 1,    /* extra argument introduced during assert
  148.                       to handle cuts */
  149.            $functor(NHd,P,NArity),
  150.        $dec_copyargs(N,Head,NHd),
  151.        arg(NArity,NHd,CutArg),
  152.        $decompile_clause(Clref, NArity, NHd, Body0),
  153.        $dec_xform(Body0,CutArg,Body,Xform)
  154.       )
  155.      ).
  156.  
  157. $dec_GetPrref(Head,Prref) :-
  158.      $assert_get_prref(Head, Prref0),
  159.      $dec_getbuffwd(Prref0,4,_,Op),
  160.      (Op =:= 91 /* jumptbreg */ ->  /* clause present, no interception */
  161.           Prref = Prref0 ;
  162.       (Op =:= 92 /* unexec */ ->  /* call intercept: trace/ET &c. */
  163.            ($functor(Head,P,N), Pred = P/N,
  164.             $dec_undo_inters(Pred,Inters),
  165.         $dec_GetPrref(Head,Prref),
  166.         $dec_do_inters(Inters,P,N)
  167.            )
  168.      )
  169.      ).
  170.  
  171. $dec_undo_inters(Pred,Inters) :-   /* undo effects of call interception */
  172.      (($symtype('_$traced_preds'(_),TType),
  173.        TType > 0,
  174.        '_$traced_preds'(Pred)
  175.       ) ->
  176.           (Inters = [trace|I0], $deb_unset(Pred)) ;
  177.       Inters = I0
  178.      ),
  179.      (($symtype('_$spy_points'(_),SType),
  180.        SType > 0,
  181.        '_$spy_points'(Pred)
  182.       ) ->
  183.           (I0 = [spy|I1], $deb_unset(Pred)) ;
  184.       I0 = I1
  185.      ),
  186.      (($symtype($deb_ugging(_),DType),
  187.        DType > 0
  188.       ) ->
  189.            (I1 = [debugging(X)], $deb_ugging(X)) ;
  190.        I1 = []
  191.      ).
  192.  
  193. $dec_do_inters([],P,A).
  194. $dec_do_inters([I|IRest],P,A) :-
  195.      $dec_do_inters1(I,P,A), $dec_do_inters(IRest,P,A).
  196.  
  197. $dec_do_inters1(trace,P,A) :- $deb_set(P,A,$deb_trace(_)).
  198. $dec_do_inters1(spy,  P,A) :- $deb_set(P,A,$deb_spy(_)).
  199. $dec_do_inters1(debugging(X),_,_) :- X =:= 1 -> $debug ; $nodebug.
  200.  
  201. /* $clause_addr/4 takes the reference of the first clause for a predicate,
  202.    and returns the reference of a clause for the predicate, backtracking
  203.    successively through all of them.                    */
  204.  
  205. $clause_addr(CurrClref,Clref,P,N) :-
  206.      $buff_code(CurrClref,4,6 /* gb */, Sop),
  207.      ((Sop =:= 44 ; Sop =:= 85) ->     /* trustmeelsefail or noop */
  208.           $clause_addr1(CurrClref,Clref,P,N) ;
  209.       ((Sop =:= 42 ; Sop =:= 43) -> /* trymeelse or retrymeelse */
  210.            ($buff_code(CurrClref,8,8 /* gpb */, NextClref),
  211.             ($clause_addr1(CurrClref,Clref,P,N) ;
  212.          $clause_addr(NextClref, Clref,P,N)  /* get next clause */
  213.         )
  214.            )
  215.      )
  216.      ).
  217.  
  218. $clause_addr1(CurrCl,Cl,P,N) :-
  219.      $buff_code(CurrCl,20,6 /* gb */,55) ->    /* check if SOB-buffer */
  220.          ($buff_code(CurrCl,36,8 /* gpb */,Clref),
  221.       $clause_addr(Clref,Cl,P,N)
  222.      ) ;
  223.      ($buff_code(CurrCl,12,6 /* gb */,77 /* jump */) ->
  224.           ($telling(X), $tell(stderr),
  225.            $writename('*** Warning: '),
  226.                $writename(P), $writename('/'), $writename(N),
  227.                $writename(' contains compiled code that is not being decompiled ***'), $nl,
  228.                $told, $tell(X),
  229.            fail
  230.           ) ;
  231.           Cl = CurrCl
  232.          ).
  233.  
  234. $decompile_clause(Clref, N, Head, Body) :-
  235.      $buff_code(Clref,12,6 /* gb */, Op),
  236.      $opcode(fail, FailOp),
  237.      Op =\= FailOp, /* make sure the clause hasn't been erased */
  238.      $dec_mk_rmap(4,4,Rmap0),
  239.      $decompile_head(Clref,1,N,Head,20,Lm,Rmap0,Rmap1),
  240.      $decompile_body(Clref,Body,Lm,Rmap1).
  241.  
  242. $decompile_head(Buff,Arg,Arity,Term,Li,Lo,Rmap0,Rmap1) :-
  243.      Arg > Arity ->
  244.           (Li = Lo, Rmap0 = Rmap1) ;
  245.            ($dec_getbuffwd(Buff,Li,Lm0,Op),
  246.        $dec_argreg(Op,Buff,Lm0,Reg),
  247.        (Reg =:= Arg ->
  248.             $dec_hdarg(Op,Buff,Term,Lm0,Lm1,Rmap0,Rmap2) ;
  249.         ( Lm1 = Li, Rmap2 = Rmap0,
  250.          $dec_map_lookup(Arg,Rmap0,X),
  251.          arg(Arg,Term,X)
  252.         )
  253.        ),
  254.        NextArg is Arg+1,
  255.        $decompile_head(Buff,NextArg,Arity,Term,Lm1,Lo,Rmap2,Rmap1)
  256.       ).
  257.  
  258. $dec_hdarg(3,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* gettval(R1,R2) */
  259.     Li1 is Li+2,    /* skip pad word */
  260.     $dec_getbuffwd(Buff,Li1,Lm1,Arg1),
  261.     $dec_getbuffwd(Buff,Lm1,Lo,Arg2),
  262.     arg(Arg1,Term,T), arg(Arg2,Term,T),
  263.     $dec_map_lookup(Arg1,Rmap,T),
  264.     $dec_map_lookup(Arg2,Rmap,T).
  265. $dec_hdarg(4,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getcon(Con, N) */
  266.     $dec_getbuffwd(Buff,Li,Lm,Arg),
  267.     arg(Arg,Term,Const),
  268.     $dec_getpsc(Buff,Lm,Lo,Const),
  269.     $dec_map_lookup(Arg,Rmap,Const).
  270. $dec_hdarg(5,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getnil(N) */
  271.     $dec_getbuffwd(Buff,Li,Lo,Arg),
  272.     arg(Arg,Term,[]),
  273.     $dec_map_lookup(Arg,Rmap,[]).
  274. $dec_hdarg(6,Buff,Term,Li,Lo,R0,R1) :-        /* getstr(Str,N) */
  275.     $dec_getbuffwd(Buff,Li,Lm1,Arg),
  276.     $dec_getpsc(Buff,Lm1,Lm2,Func),
  277.     $mkstr(Func,Str,Arity),
  278.     arg(Arg,Term,Str),
  279.     $dec_subs(1,Arity,Buff,Str,Lm2,Lo,R0,R1),
  280.     $dec_map_lookup(Arg,R1,Str).
  281. $dec_hdarg(7,Buff,Term,Li,Lo,R0,R1) :-        /* getlist(N) */
  282.     $dec_getbuffwd(Buff,Li,Lm1,Arg),
  283.     List = [_|_], arg(Arg,Term,List),
  284.     $dec_subs(1,2,Buff,List,Lm1,Lo,R0,R1),
  285.     $dec_map_lookup(Arg,R1,List).
  286. $dec_hdarg(14,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getnumcon(Num, N) */
  287.     $dec_getbuffwd(Buff,Li,Lm,Arg),
  288.     arg(Arg,Term,N),
  289.     $dec_getbuffnum(Buff,Lm,Lo,N),
  290.     $dec_map_lookup(Arg,Rmap,N).
  291. $dec_hdarg(32,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getfloatcon(Num, N) */
  292.     $dec_getbuffwd(Buff,Li,Lm,Arg),
  293.     arg(Arg,Term,N),
  294.     $dec_getbuffloat(Buff,Lm,Lo,N),
  295.     $dec_map_lookup(Arg,Rmap,N).
  296. $dec_hdarg(39,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getlist_tvar_tvar */
  297.     $dec_getbuffwd(Buff,Li,Lm0,Arg),
  298.     $dec_getbuffwd(Buff,Lm0,Lm1,R1),
  299.     $dec_getbuffwd(Buff,Lm1,Lo,R2),
  300.     $dec_map_lookup(R1,Rmap,A1),
  301.     $dec_map_lookup(R2,Rmap,A2),
  302.     Sub = [A1|A2], arg(Arg,Term,Sub),
  303.     $dec_map_lookup(Arg,Rmap,Sub).
  304. $dec_hdarg(40,Buff,Term,Li,Lo,R0,R1) :-        /* getcomma(N) */
  305.     $dec_getbuffwd(Buff,Li,Lm1,Arg),
  306.     Sub = ','(_,_), arg(Arg,Term,Sub),
  307.     $dec_subs(1,2,Buff,Sub,Lm1,Lo,R0,R1),
  308.     $dec_map_lookup(Arg,R1,Sub).
  309. $dec_hdarg(41,Buff,Term,Li,Lo,Rmap,Rmap) :-    /* getcomma_tvar_tvar */
  310.     $dec_getbuffwd(Buff,Li,Lm0,Arg),
  311.     $dec_getbuffwd(Buff,Lm0,Lm1,R1),
  312.     $dec_getbuffwd(Buff,Lm1,Lo,R2),
  313.     $dec_map_lookup(R1,Rmap,A1),
  314.     $dec_map_lookup(R2,Rmap,A2),
  315.     Sub = ','(A1,A2), arg(Arg,Term,Sub),
  316.     $dec_map_lookup(Arg,Rmap,Sub).
  317.  
  318. /* $dec_argreg/3 returns the "main" register number for an instruction in
  319.    a buffer.  Argument 1 is the opcode of the "current" instruction. */
  320.  
  321. $dec_argreg(3,Buff,Disp,N) :-            /* gettval(R,N) */
  322.      Lr is Disp + 4,        /* skip pad byte, op1 */
  323.      $buff_code(Buff,Lr,6 /* gb */, N).
  324. $dec_argreg(Op,Buff,Disp,N) :-
  325.      Op >= 4, Op =< 7, /* getcon(C,N)|getnil(N)|getstr(Str,N)|getlist(N) */
  326.      $buff_code(Buff,Disp,6 /* gb */, N).
  327. $dec_argreg(14,Buff,Disp,N) :-            /* getnumcon(Num,N) */
  328.      $buff_code(Buff,Disp,6 /* gb */, N).
  329. $dec_argreg(32,Buff,Disp,N) :-            /* getfloatcon(Num,N) */
  330.      $buff_code(Buff,Disp,6 /* gb */, N).
  331. $dec_argreg(Op,Buff,Disp,N) :-            
  332.      Op >= 39, /* getlist_tvar_tvar(N,_,_) | getcomma(N) | */
  333.      Op =< 41, /* getcomma_tvar_tvar(N,_,_) */
  334.      $buff_code(Buff,Disp,6 /* gb */, N).
  335.  
  336. /*  if we hit a "put" instruction we know we're past the head, so return an
  337.     "impossible" register number.                    */
  338. $dec_argreg(15,Buff,Disp,-1).        /* putnumcon(Num,N) */
  339. $dec_argreg(18,Buff,Disp,-1).        /* puttvar(T,R) */
  340. $dec_argreg(20,Buff,Disp,-1).        /* putcon(C,R) */
  341. $dec_argreg(21,Buff,Disp,-1).        /* putnil(R) */
  342. $dec_argreg(22,Buff,Disp,-1).        /* putstr(S,R) */
  343. $dec_argreg(23,Buff,Disp,-1).        /* putlist(R) */
  344. $dec_argreg(33,Buff,Disp,-1).        /* putfloatcon(Num,N) */
  345. $dec_argreg(58,Buff,Disp,-1).        /* movreg(T,R) */
  346. $dec_argreg(74,Buff,Disp,-1).        /* proceed */
  347. $dec_argreg(75,Buff,Disp,-1).        /* execute(P) */
  348.  
  349. $dec_subs(N,Arity,Buff,Term,Li,Lo,Rin,Rout) :-
  350.     N > Arity ->
  351.         (Li = Lo, Rin = Rout) ;
  352.     ($dec_getbuffwd(Buff,Li,Lm1,Op),
  353.      $dec_sub(Op,Buff,Sub,Lm1,Lm2,Rin,Rmid),
  354.      arg(N,Term,Sub),
  355.      N1 is N+1,
  356.      $dec_subs(N1,Arity,Buff,Term,Lm2,Lo,Rmid,Rout)
  357.     ).
  358.  
  359. $dec_sub(10,Buff,X,Li,Lo,Rmap,Rmap) :-        /* unitvar(R) */
  360.     $dec_getbuffwd(Buff,Li,Lo,R),
  361.     $dec_map_lookup(R,Rmap,X).
  362. $dec_sub(11,Buff,X,Li,Lo,Rmap,Rmap) :-        /* unitval(R) */
  363.     $dec_getbuffwd(Buff,Li,Lo,R),
  364.     $dec_map_lookup(R,Rmap,X).
  365. $dec_sub(12,Buff,Con,Li,Lo,Rmap,Rmap) :-    /* unicon(Con) */
  366.     Lm is Li+2,    /* skip pad bytes */
  367.     $dec_getpsc(Buff,Lm,Lo,Con).
  368. $dec_sub(13,Buff,[],Li,Lo,Rmap,Rmap) :-        /* uninil */
  369.     Lo is Li + 2.
  370. $dec_sub(26,Buff,X,Li,Lo,Rin,Rout) :-        /* bldtvar(R) */
  371.     $dec_getbuffwd(Buff,Li,Lo,R),
  372.     $dec_map_update(R,Rin,X,Rout).
  373. $dec_sub(27,Buff,X,Li,Lo,Rmap,Rmap) :-        /* bldtval(R) */
  374.     $dec_getbuffwd(Buff,Li,Lo,R),
  375.     $dec_map_lookup(R,Rmap,X).
  376. $dec_sub(28,Buff,Con,Li,Lo,Rmap,Rmap) :-    /* bldcon(Con) */
  377.     Lm is Li+2,    /* skip pad byte */
  378.     $dec_getpsc(Buff,Lm,Lo,Con).
  379. $dec_sub(29,Buff,[],Li,Lo,Rmap,Rmap) :-        /* bldnil */
  380.     Lo is Li + 2.
  381. $dec_sub(30,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* uninumcon(Num) */
  382.     Lm is Li+2,    /* skip pad bytes */
  383.     $dec_getbuffnum(Buff,Lm,Lo,Num).
  384. $dec_sub(31,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* bldnumcon(Num) */
  385.     Lm is Li+2,    /* skip pad bytes */
  386.     $dec_getbuffnum(Buff,Lm,Lo,Num).
  387. $dec_sub(34,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* unifloatcon(Num) */
  388.     Lm is Li+2,    /* skip pad bytes */
  389.     $dec_getbuffloat(Buff,Lm,Lo,Num).
  390. $dec_sub(35,Buff,Num,Li,Lo,Rmap,Rmap) :-    /* bldfloatcon(Num) */
  391.     Lm is Li+2,    /* skip pad bytes */
  392.     $dec_getbuffloat(Buff,Lm,Lo,Num).
  393.  
  394.  
  395. $decompile_body(Buff,Body,Loc,Rmap) :-
  396.      $dec_getbuffwd(Buff,Loc,Lm0,Op),
  397.      (Op =:= 74 ->                /* proceed */
  398.           Body = true ;
  399.       (Op =:= 75 ->            /* execute(P) */
  400.            (Lm1 is Lm0 + 2,    /* skip pad bytes */
  401.             $dec_getpsc(Buff,Lm1,_,Psc),
  402.         $mkstr(Psc,Body,Arity),
  403.         $dec_procputs(Arity,Rmap,Body)
  404.            ) ;
  405.            ($dec_bodyinst(Op,Buff,Lm0,Lm1,Rmap,Rmap0),
  406.             $decompile_body(Buff,Body,Lm1,Rmap0)
  407.            )
  408.       )
  409.      ).
  410.  
  411. $dec_bodyinst(3,Buff,Li,Lo,Rmap,Rmap) :-    /* gettval(R1,R2) */
  412.      Li1 is Li+2,    /* skip pad bytes */
  413.      $dec_getbuffwd(Buff,Li1,Lm1,Arg1),
  414.      $dec_getbuffwd(Buff,Lm1,Lo,Arg2),
  415.      $dec_map_lookup(Arg1,Rmap,T),
  416.      $dec_map_lookup(Arg2,Rmap,T).
  417. $dec_bodyinst(4,Buff,Li,Lo,Rmap,Rmap) :-    /* getcon(Con, N) */
  418.      $dec_getbuffwd(Buff,Li,Lm,R),
  419.      $dec_getpsc(Buff,Lm,Lo,Const),
  420.      $dec_map_lookup(R,Rmap,Const).
  421. $dec_bodyinst(5,Buff,Li,Lo,Rmap,Rmap) :-    /* getnil(N) */
  422.      $dec_getbuffwd(Buff,Li,Lo,R),
  423.      $dec_map_lookup(R,Rmap,[]).
  424. $dec_bodyinst(6,Buff,Li,Lo,Rin,Rout) :-        /* getstr(Str,N) */
  425.      $dec_getbuffwd(Buff,Li,Lm1,R),
  426.      $dec_getpsc(Buff,Lm1,Lm2,Func),
  427.      $mkstr(Func,Str,Arity),
  428.      $dec_map_lookup(R,Rin,Str),
  429.      $dec_subs(1,Arity,Buff,Str,Lm2,Lo,Rin,Rout).
  430. $dec_bodyinst(7,Buff,Li,Lo,Rin,Rout) :-        /* getlist(N) */
  431.      $dec_getbuffwd(Buff,Li,Lm1,R),
  432.      List = [_|_],
  433.      $dec_map_lookup(R,Rin,List),
  434.      $dec_subs(1,2,Buff,List,Lm1,Lo,Rin,Rout).
  435. $dec_bodyinst(14,Buff,Li,Lo,Rmap,Rmap) :-    /* getnumcon(Num, N) */
  436.      $dec_getbuffwd(Buff,Li,Lm,R),
  437.      $dec_getbuffnum(Buff,Lm,Lo,N),
  438.      $dec_map_lookup(R,Rmap,N).
  439. $dec_bodyinst(15,Buff,Li,Lo,Rin,Rout) :-
  440.      $dec_getbuffwd(Buff,Li,Lm,R),        /* putnumcon(Num,R) */
  441.      $dec_getbuffnum(Buff,Lm,Lo,Num),
  442.      $dec_map_update(R,Rin,Num,Rout).
  443. $dec_bodyinst(18,Buff,Li,Lo,Rin,Rout) :-    /* puttvar(R1, R2) */
  444.      Li1 is Li + 2,
  445.      $dec_getbuffwd(Buff,Li1,Lm,R1),
  446.      $dec_getbuffwd(Buff,Lm,Lo,R2),
  447.      $dec_map_update(R1,Rin,X,Rmid),
  448.      $dec_map_update(R2,Rmid,X,Rout).
  449. $dec_bodyinst(20,Buff,Li,Lo,Rin,Rout) :-
  450.      $dec_getbuffwd(Buff,Li,Lm,R),        /* putcon(Con,R) */
  451.      $dec_getpsc(Buff,Lm,Lo,Con),
  452.      $dec_map_update(R,Rin,Con,Rout).
  453. $dec_bodyinst(21,Buff,Li,Lo,Rin,Rout) :- 
  454.      $dec_getbuffwd(Buff,Li,Lo,R),        /* putnil(R) */
  455.      $dec_map_update(R,Rin,[],Rout).
  456. $dec_bodyinst(22,Buff,Li,Lo,Rin,Rout) :-
  457.      $dec_getbuffwd(Buff,Li,Lm0,R),        /* putstr(Str,R) */
  458.      $dec_getpsc(Buff,Lm0,Lm1,Psc),
  459.      $mkstr(Psc,Str,Arity),
  460.      $dec_subs(1,Arity,Buff,Str,Lm1,Lo,Rin,Rmid),
  461.      $dec_map_update(R,Rmid,Str,Rout).
  462. $dec_bodyinst(23,Buff,Li,Lo,Rin,Rout) :- 
  463.      List = [_|_],                /* putlist(R) */
  464.      $dec_getbuffwd(Buff,Li,Lm,R),
  465.      $dec_map_update(R,Rin,List,Rmid),
  466.      $dec_subs(1,2,Buff,List,Lm,Lo,Rmid,Rout).
  467. $dec_bodyinst(32,Buff,Li,Lo,Rmap,Rmap) :-    /* getfloatcon(Num, N) */
  468.      $dec_getbuffwd(Buff,Li,Lm,R),
  469.      $dec_getbuffloat(Buff,Lm,Lo,N),
  470.      $dec_map_lookup(R,Rmap,N).
  471. $dec_bodyinst(33,Buff,Li,Lo,Rin,Rout) :-
  472.      $dec_getbuffwd(Buff,Li,Lm,R),        /* putfloatcon(Num,R) */
  473.      $dec_getbuffloat(Buff,Lm,Lo,Num),
  474.      $dec_map_update(R,Rin,Num,Rout).
  475. $dec_bodyinst(39,Buff,Li,Lo,Rmap,Rmap) :-    /* getlist_tvar_tvar */
  476.      $dec_getbuffwd(Buff,Li,Lm0,R0),
  477.      $dec_getbuffwd(Buff,Lm0,Lm1,R1),
  478.      $dec_getbuffwd(Buff,Lm1,Lo,R2),
  479.      $dec_map_lookup(R1,Rmap,A1),
  480.      $dec_map_lookup(R2,Rmap,A2),
  481.      $dec_map_lookup(R0,Rmap,[A1|A2]).
  482. $dec_bodyinst(40,Buff,Li,Lo,Rin,Rout) :-    /* getcomma(N) */
  483.      $dec_getbuffwd(Buff,Li,Lm1,R),
  484.      Sub = ','(_,_), $dec_map_lookup(R,Rin,Sub),
  485.      $dec_subs(1,2,Buff,Sub,Lm1,Lo,Rin,Rout).
  486. $dec_bodyinst(41,Buff,Li,Lo,Rmap,Rmap) :-    /* getcomma_tvar_tvar */
  487.      $dec_getbuffwd(Buff,Li,Lm0,R0),
  488.      $dec_getbuffwd(Buff,Lm0,Lm1,R1),
  489.      $dec_getbuffwd(Buff,Lm1,Lo,R2),
  490.      $dec_map_lookup(R1,Rmap,A1),
  491.      $dec_map_lookup(R2,Rmap,A2),
  492.      $dec_map_lookup(R0,Rmap,','(A1,A2)).
  493. $dec_bodyinst(58,Buff,Li,Lo,Rin,Rout) :-      /* movreg(R1,R2) */
  494.      Lm0 is Li + 2,    /* skip pad bytes */
  495.      $dec_getbuffwd(Buff,Lm0,Lm1,R1),
  496.      $dec_getbuffwd(Buff,Lm1,Lo,R2),
  497.      $dec_map_lookup(R1,Rin,Val),
  498.      $dec_map_update(R2,Rin,Val,Rout).
  499.  
  500. $dec_procputs(Arg,Rmap,Body) :-
  501.      Arg =:= 0 ->
  502.           true ;
  503.       ($dec_map_lookup(Arg,Rmap,Val),
  504.        arg(Arg,Body,Val),
  505.        Next is Arg - 1,
  506.        $dec_procputs(Next,Rmap,Body)
  507.       ).
  508.  
  509. $dec_xform(Body0,C,Body1,N) :-
  510.      N > 0 -> $dec_xform_1(Body0,C,Body1) ; Body0 = Body1.
  511.  
  512. $dec_xform_1(','(A0,A1,A2,A3),C,(B0,B1,B2,B3)) :-
  513.      !,
  514.      $dec_xform_1(A0,C,B0),
  515.      $dec_xform_1(A1,C,B1),
  516.      $dec_xform_1(A2,C,B2),
  517.      $dec_xform_1(A3,C,B3).
  518. $dec_xform_1(','(A0,A1),C,','(B0,B1)) :-
  519.      !,
  520.      $dec_xform_1(A0,C,B0),
  521.      $dec_xform_1(A1,C,B1).
  522. $dec_xform_1(';'(A0,A1),C,';'(B0,B1)) :-
  523.      !,
  524.      $dec_xform_1(A0,C,B0),
  525.      $dec_xform_1(A1,C,B1).
  526. $dec_xform_1('->'(A0,A1),C,'->'(B0,B1)) :-
  527.      !,
  528.      $dec_xform_1(A0,C,B0),
  529.      $dec_xform_1(A1,C,B1).
  530. $dec_xform_1('_$cutto'(V),C,Lit) :-
  531.      !,
  532.      (C == V -> Lit = '!' ; Lit = '_$cutto'(V)).
  533. $dec_xform_1(L,_,L).
  534.  
  535.  
  536. $dec_errmsg(Type,P,N) :-
  537.      $telling(X), $tell(stderr),
  538.      $writename('*** Warning: '),
  539.      $writename(P), $writename('/'), $writename(N),
  540.      $dec_errmsg1(Type, ErrType),
  541.      $writename(ErrType), $writename(', cannot decompile ***'), $nl,
  542.      $told, $tell(X).
  543.  
  544. $dec_errmsg1(0, ' is undefined').
  545. $dec_errmsg1(2, ' is compiled').
  546.  
  547. /*  The following predicates manipulate a "register map", which is
  548.     basically an array of 256 elements represented as a complete quadtree
  549.     of height 4.                            */
  550.  
  551. $dec_mk_rmap(Level,Arity,Map) :-
  552.      $functor(Map,rm,Arity),
  553.      (Level =:= 1 ->
  554.          true ;
  555.      (Lev1 is Level - 1,
  556.       $dec_mk_rmaps(Arity,Arity,Lev1,Map)
  557.      )
  558.      ).
  559.  
  560. $dec_mk_rmaps(Argno,Arity,Level,Map) :-
  561.      Argno =:= 0 ->
  562.          true ;
  563.      (arg(Argno,Map,SubMap),
  564.       $dec_mk_rmap(Level,Arity,SubMap),
  565.       NextArg is Argno - 1,
  566.       $dec_mk_rmaps(NextArg,Arity,Level,Map)
  567.      ).
  568.  
  569. $dec_map_lookup(I,Tree,Val) :-
  570.      Index is I - 1,
  571.      $dec_map_lookup(4,Index,Tree,Val).
  572.  
  573. $dec_map_lookup(Level,Index,Tree,Val) :-
  574.     $get_currindex(Level,Index,CurrInd),
  575.     (Level =:= 1 ->
  576.          arg(CurrInd,Tree,Val) ;
  577.      (arg(CurrInd,Tree,SubTree),
  578.       NewLevel is Level - 1,
  579.       $dec_map_lookup(NewLevel,Index,SubTree,Val)
  580.      )
  581.     ).
  582.  
  583. $dec_map_update(I,Tree,Val,NTree) :-
  584.      Index is I-1,
  585.      $dec_map_update(4,Index,Tree,Val,NTree).
  586.  
  587. $dec_map_update(Level,Index,Tree,Val,NTree) :-
  588.     NTree = rm(_,_,_,_),
  589.     $get_currindex(Level,Index,CurrInd),
  590.     (Level =:= 1 ->
  591.      $subst_arg(4,CurrInd,Tree,Val,NTree) ;
  592.      (arg(CurrInd,Tree,SubTree),
  593.       NewLevel is Level - 1,
  594.       $dec_map_update(NewLevel,Index,SubTree,Val,NSubTree),
  595.       $subst_arg(4,CurrInd,Tree,NSubTree,NTree)
  596.      )
  597.      ).
  598.  
  599. $subst_arg(N,I,Tree,Val,NTree) :-
  600.      N =:= 0 ->                /* done! */
  601.           true ;
  602.       ((N =:= I ->            /* make the change */
  603.            arg(N,NTree,Val) ;
  604.            (arg(N,Tree,Arg), arg(N,NTree,Arg))
  605.            ),
  606.        N1 is N - 1,
  607.        $subst_arg(N1,I,Tree,Val,NTree)
  608.       ).
  609.  
  610. $get_currindex(Level,Index,N) :-
  611.     Shift is (Level-1) << 1,  /* Shift = 2*(Level-1) */
  612.     Mask is 2'11 << Shift,
  613.     N is ((Index /\ Mask) >> Shift) + 1.
  614.  
  615. $dec_copyargs(N,T1,T2) :-
  616.      N =:= 0 ->
  617.           true ;
  618.       (arg(N,T1,X), arg(N,T2,X),
  619.        N1 is N - 1,
  620.        $dec_copyargs(N1,T1,T2)
  621.       ).
  622.  
  623. % The new version of listing/0 which lists all signatures, structures and
  624. % functors defined at the top level.
  625.  
  626. $listing :-
  627.     $setof(X, D0^D1^D2^D3^$module_signature(X,D0,D1,D2,D3),
  628.            Sigs),
  629.     $list_signatures(Sigs),
  630.     $setof(X, D0^D1^D2^D3^$module_structure(X,D0,D1,D2,D3),
  631.            Strnames),
  632.     $grab_structure_tags(Strnames, Strs),
  633.     $grab_predicates(Strnames,Strs,Preds),
  634.     $list_structures(Preds),
  635.     $setof(X, D0^D1^D2^D3^D4^D5^D6^D7^D8^
  636.                   $module_functor(X,D0,D1,D2,D3,D4,D5,D6,D7,D8),
  637.           Funs),
  638.     $list_functors(Funs).
  639.  
  640. $listing.
  641.  
  642. % $list_module/1 lists the module corresponding to the argument tag. Can list
  643. % any structure, including sub-structures not listed by listing/0.
  644.  
  645. $list_module(Tag) :-
  646.     $isa_structuretag(Tag),
  647.     $get_structure(Tag,Name,Substrs,Preds,Funs),
  648.     $grab_predicates([Name],[Tag],[str(_,_,Actualpreds)]),
  649.     $writename('structure '),
  650.     $write(Name),
  651.     $writename(' ='), $nl,
  652.     $writename('  struct'), $nl,
  653.     $list_struct(Substrs,Preds,Funs),
  654.     $list_mapped_functions(Tag),
  655.     $list_preds(Actualpreds,Tag),
  656.     $writename('  end.'), $nl.
  657.  
  658. % List all signatures.
  659.  
  660. $list_signatures(List) :-
  661.     List == [] -> true ;
  662.         ( List = [Name|Rest],
  663.           $module_signature(Name,_,Substrs,Preds,Funs), !,
  664.           $writename('signature '),
  665.           $writename(Name), 
  666.           $writename(' ='), $nl,
  667.           $writename('  sig'), $nl,
  668.           $list_struct(Substrs,Preds,Funs),
  669.           $writename('  end.'), $nl,
  670.           $list_signatures(Rest) ).
  671.  
  672. % List all structures.
  673. % Note that in general the list of predicates given in the structure signature,
  674. % is not an exhaustive list of the predicates actually in the structure.
  675.  
  676. $list_structures(List) :-
  677.     List == [] -> true ;
  678.         ( List = [str(Name,Tag,Actualpreds)|Rest],
  679.           $module_structure(Name,Tag,Substrs,Preds,Funs), !,
  680.           $writename('structure '),
  681.           $writename(Name),
  682.           $writename(' ='), $nl,
  683.           $writename('  struct'), $nl,
  684.           $list_struct(Substrs,Preds,Funs),
  685.           $list_mapped_functions(Tag),
  686.           $list_preds(Actualpreds,Tag),
  687.           $writename('  end.'), $nl,
  688.           $list_structures(Rest) ).
  689.  
  690. % List all functors.
  691.  
  692. $list_functors(List) :-
  693.     List == [] -> true ;
  694.         ( List = [Name|Rest],
  695.           $module_functor(Name,_,Params,_,_,_,Strexpr,_,_,_), !,
  696.           $writename('functor '),
  697.           $univ(Functor,[Name|Params]),
  698.           $write(Functor),
  699.           $writename(' ='), $nl,
  700.           $writename('  struct'), $nl,
  701.           ( Strexpr = Code/_ -> $list_functor_code(Code) ;
  702.                             $list_functor_code(Strexpr) ),
  703.           $writename('  end.'), $nl,
  704.           $list_functors(Rest) ).
  705.  
  706. % List the contents of a signature, displaying any references to sub-structures
  707. % as '...'.
  708.  
  709. $list_struct(Substrs,Preds,Funs) :-
  710.     $remove_sub_items(Substrs, Substrs0, $flag),
  711.     $remove_sub_items(Preds, Preds0, $flag),
  712.     $remove_sub_items(Funs, Funs0, $flag),
  713.     ( Substrs0 == [] -> true ;
  714.                ( $writename('    structure '),
  715.                  $list_list(Substrs0) ) ),
  716.     ( Preds0 == [] -> true ;
  717.              ( $writename('    pred '),
  718.                $list_list(Preds0) ) ),
  719.     ( Funs0 == [] -> true ;
  720.             ( $writename('    fun '),
  721.               $list_list(Funs0) ) ).
  722.  
  723. $remove_sub_items([], [], $flag).
  724. $remove_sub_items([], ['...'], $flagset).
  725. $remove_sub_items([_ : _ / _ ---> _|Rest], Result, _) :- !,
  726.     $remove_sub_items(Rest, Result, $flagset).
  727. $remove_sub_items([_ : _ ---> _|Rest], Result, _) :- !,
  728.     $remove_sub_items(Rest, Result, $flagset).
  729. $remove_sub_items([Item|Rest], [Item|Result], Flag) :-
  730.     $remove_sub_items(Rest, Result, Flag).
  731.  
  732. $list_list(['...']) :- !,
  733.     $writename('... .'),$nl.
  734. $list_list([Name ---> _]) :- !,
  735.     $write(Name),$writename('.'),$nl.
  736. $list_list([Name ---> _|Tail]) :-
  737.     $write(Name),
  738.     $writename(' and '),
  739.     $list_list(Tail).
  740.  
  741. % List any 'fun X = Y' functions declared in the current structure.
  742.  
  743. $list_mapped_functions(Tag) :-
  744.     $symtype($mapped_function(_,_,_,_), Type),
  745.     Type > 0,
  746.     $mapped_function(X,Arity,Y,Tag),
  747.     $dismantle_name(X,X0,_),
  748.     $dismantle_name(Y,Y0,_),
  749.     $writename('    fun '),
  750.     $write(X0/Arity = Y0),
  751.     $writename('.'), $nl, fail.
  752. $list_mapped_functions(_).
  753.  
  754. % List the clauses given in a functor body.
  755.  
  756. $list_functor_code(List) :-
  757.     List == [] -> true ;
  758.         ( List = [Clause|Rest],
  759.           not(not($list_portray_clause(Clause,perv))),
  760.           $list_functor_code(Rest) ).
  761.  
  762. % Given a list of tags (corresponding to top level structures only), find
  763. % their names.
  764.  
  765. $grab_structure_tags([], []).
  766. $grab_structure_tags([Name|Names], [Tag|Tags]) :-
  767.     $module_structure(Name, Tag, S, P, F), !,
  768.     $grab_structure_tags(Names, Tags).
  769.  
  770. % The naive way of listing to contents of a structure is to call 
  771. % current_predicate/2, checking each returned predicate name for membership in
  772. % the current structure (by comparing tags), displaying it if necessary, and
  773. % completing when current_predicate/2 eventually fails.
  774. % However, the database is massive (as it includes the system predicates too)
  775. % and so we gather together all the predicates only once (here), and increase
  776. % efficiency enormously.
  777. % The predicate actually returns a list of the following :
  778. %           str(Name, Tag, List)
  779. % where Name is the name of the structure whose tag is Tag, and which contains
  780. % the predicates given in List.
  781.  
  782. $grab_predicates(Names, List,Result) :-
  783.     bagof(pred(Tag,Term), Name^Term^Tag^Dummy^
  784.                      ( $current_predicate(Name,Term),
  785.                    $dismantle_name(Name,Dummy,Tag),
  786.                $memberchk(Tag, List) ), Preds),
  787.     $grab_predicates(Names, List, Preds, Result), !.
  788.  
  789. $grab_predicates([],[],_,[]).
  790. $grab_predicates([Name|Names],[Tag|Tags],Preds,
  791.              [str(Name,Tag,List)|Rest]) :-
  792.     $grab_predicates(Tag, Preds, Newpreds, List),
  793.     $grab_predicates(Names, Tags, Newpreds, Rest).
  794.  
  795. $grab_predicates(_,[],[],[]).
  796. $grab_predicates(Tag,[pred(Tag,Term)|Preds],Newpreds,[Term|Rest]) :-
  797.     $grab_predicates(Tag,Preds,Newpreds,Rest).
  798. $grab_predicates(Tag,[Pred|Preds],[Pred|Newpreds],Rest) :-
  799.     $grab_predicates(Tag,Preds,Newpreds,Rest).
  800.  
  801. % List the clauses in a structure, given a list of predicate names.
  802.  
  803. $list_preds([],_).
  804. $list_preds([Term|Tail],Tag) :-
  805.     $decompile(Term,Body,_,1),
  806.     not(not($list_portray_clause((Term :- Body),Tag))),
  807.     fail.
  808. $list_preds([_|Tail],Tag) :-
  809.     $list_preds(Tail,Tag).
  810.  
  811. % All clause printing for the module listing/0 is passed to this version
  812. % of portray_clause. This is because we need each clause indented by a few
  813. % spaces to the output looks reasonable.
  814. % The code is almost a direct copy of that in $portray.P, which only a few
  815. % minor changes.
  816. % Similarly, the code for write has been copied here and named list_write/1,
  817. % so that we can get it to stop printing the path of an item that belongs
  818. % in the module we are printing.
  819.  
  820. $list_portray_clause((H :- B),Tag) :-
  821.     $list_portray_namevars((H :- B), 0,_),
  822.         !,
  823.         $writename('    '),
  824.         $list_write(H,Tag),
  825.         (B ?= true ->
  826.              true ;
  827.              ($writename(' :- '), $nl,
  828.               $list_portray_body(B,8,8,Tag))),
  829.         $writename('.'),
  830.         $nl.
  831. $list_portray_clause(Fact,Tag) :-
  832.     $list_portray_namevars(Fact,0,_),
  833.         $writename('    '),
  834.         $list_write(Fact,Tag),
  835.         $writename('.'),
  836.         $nl.
  837.  
  838. $list_portray_namevars(X,N,N1) :-
  839.         var(X), !,
  840.         $name(N,Nname),
  841.         $append("V",Nname,XName),
  842.         $name(X,XName),
  843.         N1 is N + 1.
  844. $list_portray_namevars(A,N,N) :- atomic(A), !.
  845. $list_portray_namevars(Str,N,N1) :-
  846.         $arity(Str,Arity),
  847.         $list_portray_namevars_str(1,Arity,Str,N,N1).
  848.  
  849. $list_portray_namevars_str(Arg,Arity,Str,N0,N1) :-
  850.         Arg > Arity ->
  851.              N1 = N0 ;
  852.              (arg(Arg,Str,Sub),
  853.               $list_portray_namevars(Sub,N0,N2),
  854.               NextArg is Arg + 1,
  855.               $list_portray_namevars_str(NextArg,Arity,Str,N2,N1)
  856.              ).
  857.  
  858. $list_portray_body(','(G1,G2),LT,RT,Tag) :-
  859.     !,
  860.     ($list_portray_CompoundGoal(G1) ->
  861.          ($tab(LT), $writename('('), T1 = 0) ;
  862.          T1 = LT),
  863.     $list_portray_body(G1,T1,RT,Tag),
  864.     ($list_portray_CompoundGoal(G1) ->
  865.          ($nl,$tab(LT), $writename(')')) ;
  866.          true),
  867.     $writename(','), $nl,
  868.     (($list_portray_CompoundGoal(G2), G2 \= ','(_,_)) ->
  869.          Parens = 1 ; Parens = 0),
  870.     (Parens =:= 1 ->
  871.          ($tab(LT), $writename('('), T2 = 0) ;
  872.          T2 = RT),
  873.     $list_portray_body(G2,T2,RT,Tag),
  874.     (Parens =:= 1 ->
  875.          ($nl,$tab(LT), $writename(')')) ;
  876.          true).
  877. $list_portray_body(';'('->'(If,Then),Else),LT,RT,Tag) :-
  878.     !,
  879.     ($list_portray_CompoundGoal(If) ->
  880.          ($tab(LT), $writename('('),
  881.           $list_portray_conj(If,Tag),
  882.           $writename(')')
  883.          ) ;
  884.          $list_portray_body(If,LT,RT,Tag)),
  885.     $writename(' ->'), $nl,
  886.     T1 is RT + 4,
  887.     $list_portray_body(';'(Then,Else),T1,T1,Tag).
  888. $list_portray_body(';'(G1,G2),LT,RT,Tag) :-
  889.     !,
  890.     ($list_portray_CompoundGoal(G1) ->
  891.          ($tab(LT), $writename('('), T1 = 0) ;
  892.          T1 = LT),
  893.     $list_portray_body(G1,T1,RT,Tag),
  894.     ($list_portray_CompoundGoal(G1) ->
  895.          ($nl,$tab(LT), $writename(')')) ;
  896.          true),
  897.     $writename(' ;'), $nl,
  898.     (($list_portray_CompoundGoal(G2), G2 \= ';'(_,_)) ->
  899.           Parens = 1 ; Parens = 0),
  900.     (Parens =:= 1 ->
  901.          ($tab(LT), $writename('('), $nl, T2 is LT + 1) ;
  902.          T2 = LT),
  903.     $list_portray_body(G2,T2,RT,Tag),
  904.     (Parens =:= 1 ->
  905.          ($nl,$tab(LT), $writename(')')) ;
  906.          true).
  907. $list_portray_body(C,T,_,Tag) :-
  908.     $tab(T),
  909.     $list_write(C,Tag).
  910.  
  911. $list_portray_conj(','(C1,C2),Tag) :-
  912.      !,
  913.      $list_portray_conj(C1,Tag),
  914.      $writename(', '),
  915.      $list_portray_conj(C2,Tag).
  916. $list_portray_conj(';'('->'(If,Then),Else),Tag) :-
  917.      !,
  918.      $writenam('( '),
  919.      $list_portray_conj(If,Tag), $writename(' -> '),
  920.      $list_portray_conj(Then,Tag), $writename(' ; '),
  921.      $list_portray_conj(Else,Tag), $writename(' )').
  922. $list_portray_conj(';'(C1,C2),Tag) :-
  923.      !,
  924.      $writename('( '),
  925.      $list_portray_conj(C1,Tag), $writename(' ;'),
  926.      $list_portray_conj(C2,Tag), $writename(' )').
  927. $list_portray_conj('->'(C1,C2),Tag) :-
  928.      !,
  929.      $writename('( '),
  930.      $list_portray_conj(C1,Tag), $writename(' -> '),
  931.      $list_portray_conj(C2,Tag), $writename(' )').
  932. $list_portray_conj(Lit,Tag) :- $list_write(Lit,Tag).
  933.  
  934. $list_portray_CompoundGoal(','(_,_)).
  935. $list_portray_CompoundGoal(';'(_,_)).
  936. $list_portray_CompoundGoal('->'(_,_)).
  937.  
  938. $list_write(T,Tag) :- $list_write(T,999,Tag).
  939.  
  940. $list_write(T,_,Tag) :- var(T), !, 
  941.     $list_writename(T,Tag).
  942. $list_write([],_,Tag) :- !, 
  943.     $list_writename([],Tag).
  944. $list_write([X|Y],_,Tag) :- !, 
  945.     $put(0'[), $list_write(X,999,Tag), $list_writetail(Y,Tag).
  946. $list_write(T,Prec,Tag) :- $structure(T), !, 
  947.   $functor0(T, P), $arity(T, N),
  948.   (N=:=1 ->
  949.     ($read_curr_op(Opprec,fx,P) ->
  950.         Nprec is Opprec-1,$list_writepreop(P,T,Prec,Opprec,Nprec,Tag);
  951.      $read_curr_op(Opprec,fy,P) ->
  952.         $list_writepreop(P,T,Prec,Opprec,Opprec,Tag);
  953.      $read_curr_op(Opprec,xf,P) ->
  954.         Nprec is Opprec-1,$list_writepostop(P,T,Prec,Opprec,Nprec,Tag);
  955.      $read_curr_op(Opprec,yf,P) ->
  956.         $list_writepostop(P,T,Prec,Opprec,Opprec,Tag);
  957.         $list_writestr(P,N,T,Tag)
  958.     );
  959.   N=:=2 ->
  960.    ($read_curr_op(Opprec,xfx,P) ->
  961.        Nprec is Opprec-1,$list_writebinop(P,T,Prec,Opprec,Nprec,Nprec,Tag);
  962.     $read_curr_op(Opprec,xfy,P) ->
  963.        Nprec is Opprec-1,$list_writebinop(P,T,Prec,Opprec,Nprec,Opprec,Tag);
  964.     $read_curr_op(Opprec,yfx,P) ->
  965.        Nprec is Opprec-1,$list_writebinop(P,T,Prec,Opprec,Opprec,Nprec,Tag);
  966.        $list_writestr(P,N,T,Tag)
  967.    );
  968.   $list_writestr(P,N,T,Tag)
  969.   ).
  970.  
  971. $list_write(T,_,Tag) :- $list_writename(T,Tag).
  972.  
  973. $list_writestr(P,N,T,Tag) :-
  974.         $list_writename(P,Tag), $put(0'(), arg(1, T, X), $list_write(X,999,Tag),
  975.         $list_writearg(T, N, 1,Tag), $put(0')).
  976.  
  977. $list_writebinop(Op,Term,Oldp,Curp,Newlp,Newrp,Tag) :-
  978.         arg(1,Term,Arg1),
  979.         arg(2,Term,Arg2),
  980.         (Curp > Oldp ->
  981.                 $put(0'(),
  982.                 $list_write(Arg1,Newlp),$tab(1),$list_writename(Op,Tag),
  983.                 $tab(1),$list_write(Arg2,Newrp,Tag),
  984.                 $put(0'))
  985.               ;
  986.                 $list_write(Arg1,Newlp,Tag),$tab(1),$list_writename(Op,Tag),
  987.                 $tab(1),$list_write(Arg2,Newrp,Tag)
  988.         ).
  989.  
  990.  
  991. $list_writepreop(Op,Term,Oldp,Curp,Newp,Tag) :-
  992.         arg(1,Term,Arg),
  993.         (Curp > Oldp ->
  994.                 $put(0'(),
  995.                 $list_writename(Op,Tag),$tab(1),$list_write(Arg,Newp,Tag),
  996.                 $put(0'))
  997.               ;
  998.                 $list_writename(Op,Tag),$tab(1),$list_write(Arg,Newp,Tag)
  999.         ).
  1000.  
  1001. $list_writepostop(Op,Term,Oldp,Curp,Newp,Tag) :-
  1002.         arg(1,Term,Arg),
  1003.         (Curp > Oldp ->
  1004.                 $put(0'(),
  1005.                 $list_write(Arg,Newp,Tag),$tab(1),$list_writename(Op,Tag),
  1006.                 $put(0'))
  1007.               ;
  1008.                 $list_write(Arg,Newp,Tag),$tab(1),$list_writename(Op,Tag)
  1009.         ).
  1010.  
  1011. $list_writearg(T, N, N,Tag) :- !.
  1012. $list_writearg(T, N, M,Tag) :- 
  1013.     L is M + 1, $put(0',), arg(L, T, X),
  1014.         $list_write(X,999,Tag), $list_writearg(T, N, L,Tag).
  1015.  
  1016. $list_writetail(X,Tag) :- var(X), ! , 
  1017.     $put(0'|), $list_writename(X,Tag), $put(0']).
  1018. $list_writetail([X|Y],Tag) :- !, 
  1019.     $put(0',), $list_write(X,999,Tag), $list_writetail(Y,Tag).
  1020. $list_writetail([],Tag) :- !, 
  1021.     $put(0']).
  1022. $list_writetail(X,Tag) :- 
  1023.     $put(0'|), $list_write(X,999,Tag), $put(0']).
  1024.  
  1025. $list_writename(Name,Tag) :-
  1026.     $dismantle_name(Name,Newname,Tag) ->
  1027.                 $writename(Newname) ;
  1028.             $write(Name).
  1029.  
  1030. /* ----------------------------- $decompile.P ----------------------------- */
  1031.  
  1032.